Experimental Manuals FPGA for Beginners Pocket Boards PRA006/PRA010

Understand What Ethernet is and How it Works, the Relationship Between Different Interface Types (MII, GMII, RGMII) , Ethernet Experiment – FPGA Beginner Study Board PRA006, PRA010 Experiment 14

Experiment 14 Ethernet Experiment

14.1 Experiment Objective

  1. Understand what Ethernet is and how it works
  2. Familiar with the relationship between different interface types (MII, GMII, RGMII) and their advantages and disadvantages (the development board uses RGMII)
  3. Combine the development board to complete the transmission and reception of data and verify it

14.2 Experiment Implement

  1. Perform a loopback test to check if the hardware is working properly.
  2. Performing data verification
  3. Perform data transmission verification

14.3 Experiment

14.3.1 Experiment Principle

Ethernet is a baseband LAN technology. Ethernet communication is a communication method that uses coaxial cable as a network medium and uses carrier multi-access and collision detection mechanisms. The data transmission rate reaches 1 Gbit/s, which can satisfy the need for data transfer of non-persistent networks. As an interconnected interface, the Ethernet interface is very widely used. There are many types of Gigabit Ethernet MII interfaces, and GMII and RGMII are commonly used.

MII interface has a total of 16 lines. See Fig 14. 1.

Figure 14.1 MII interface

 

RXD (Receive Data) [3:0]: data reception signal, a total of 4 signal lines;

TX_ER (Transmit Error): Send data error prompt signal, synchronized to TX_CLK, active high, indicating that the data transmitted during TX_ER validity period is invalid. For 10Mbps rate, TX_ER does not work;

RX_ER (Receive Error): Receive data error prompt signal, synchronized to RX_CLK, active high, indicating that the data transmitted during the valid period of RX_ER is invalid. For 10Mbps, RX_ER does not work;

TX_EN (Transmit Enable): Transmit enable signal, only the data transmitted during the valid period of TX_EN is valid;

RX_DV (Receive Data Valid): Receive data valid signal, the action type is TX_EN of the transmission channel;

TX_CLK: Transmit reference clock, the clock frequency is 25MHz at 100Mbps, and the clock frequency is 2.5MHz at 10Mbps. Note that the direction of TX_CLK clock is from the PHY side to the MAC side, so this clock is provided by the PHY;

RX_CLK: Receive data reference clock, the clock frequency is 25MHz at 100Mbps, and the clock frequency is 2.5MHz at 10Mbps. RX_CLK is also provided by the PHY side;

CRS: Carrier Sense, carrier detect signal, does not need to synchronize with the reference clock. If there is data transmission, CRS is valid. In addition, CRS is effective only if PHY is in half-duplex mode;

COL: Collision detection signal, does not need to be synchronized to the reference clock, is valid only if PHY is in half-duplex mode.

GMII interface is shown in Figure 14.2.

Figure 14.2 GMII interface

Compared with the MII interface, the data width of the GMII is changed from 4 bits to 8 bits. The control signals in the GMII interface such as TX_ER, TX_EN, RX_ER, RX_DV, CRS, and COL function the same as those in the MII interface. The frequencies of transmitting reference clock GTX_CLK and the receiving reference clock RX_CLK are both 125 MHz (1000 Mbps / 8 = 125 MHz).

There is one point that needs special explanation here, that is, the transmitting reference clock GTX_CLK is different from the TX_CLK in the MII interface. The TX_CLK in the MII interface is provided by the PHY chip to the MAC chip, and the GTX_CLK in the GMII interface is provided to the PHY chip by the MAC chip. The directions are different.

In practical applications, most GMII interfaces are compatible with MII interfaces. Therefore, the general GMII interface has two transmitting reference clocks: TX_CLK and GTX_CLK (the directions of the two are different, as mentioned above). When used as the MII mode, TX_CLK and 4 of the 8 data lines are used.

See Figure 14.3 for RGMII interface.

Figure 14.3 RGMII interface

RGMII, or reduced GMII, is a simplified version of GMII, which reduces the number of interface signal lines from 24 to 14 (COL/CRS port status indication signals, not shown here), the clock frequency is still 125MHz, and the TX/RX data width is changed from 8 to 4 bits. To keep the transmission rate of 1000 Mbps unchanged, the RGMII interface samples data on both the rising and falling edges of the clock. TXD[3:0]/RXD[3:0] in the GMII interface is transmitted on the rising edge of the reference clock, and TXD[7:4]/RXD[7:4] in the GMII interface is transmitted on the falling edge of the reference clock. RGMI is also compatible with both 100Mbps and 10Mbps rates, with reference clock rates of 25MHz and 2.5MHz, respectively.

The TX_EN signal line transmits TX_EN and TX_ER information, TX_EN is transmitted on the rising edge of TX_CLK, and TX_ER is transmitted on the falling edge. Similarly, RX_DV and RX_ER are transmitted on the RX_DV signal line, and RX_DV is transmitted on the rising edge of RX_CLK, and RX_ER is transmitted on the falling edge.

14.3.2 Hardware Design

Figure 14.4 Schematics of RTL8211E-VB

The RTL8211E-VB chip is used to form a Gigabit Ethernet module on the experiment board. The schematics is shown in Figure 14. 4. The PHY chip is connected to the FPGA by receiving and transmitting two sets of signals. The receiving group signal prefix is RG0_RX, and the transmitting group signal prefix is RG0TX, which is composed of a control signal CTL, a clock signal CK and four data signals 3-0. RG0_LED0 and RG0_LED1 are respectively connected to the network port yellow signal light and green signal light. At the same time, the FPGA can configure the PHY chip through the clock line NPHY_MDC and the data line NPHY_MDIO.

14.3.3 Design of the Program

  1. Loopback test design(test1)

The first step: introduction of the program

The loopback test is straightforward. Simply output the input data.

module test1 (

input rst,

input rxc,

input rxdv,

input [3:0] rxd,

output txc,

output txen,

output [3:0] txd,

);

 

assign txd = rxd;

assign txen = rxdv;

assign txc = rxc;

endmodule

(Note: Each program in this experiment contains a smi_ctrl module. In the config folder, it is a setting module for the PHY chip, to solve the problem that some computers cannot connect to the network port normally, and will not explain in detail)

The second step: pin assignment

See Table 14.1 for the pin assignment

Table 14.1 Ethernet experiment pin mapping

Signal Name Network Label FPGA Pin Port Description
rxc RG0_RXCK 24 Input clock
rxdv RG0_RXCTL 34 Input control signal
rxd[3] RG0_RX3 28 Receive data (4-bit bilateral edge)
rxd[2] RG0_RX2 31
rxd[1] RG0_RX1 32
rxd[0] RG0_RX0 33
txc RG0_TXCK 43 Output clock
txen RG0_TXCTL 42 Output control signal
txd[3] RG0_TX3 46 Transmit data (4-bit bilateral edge)
txd[2] RG0_TX2 49
txd[1] RG0_TX1 50
txd[0] RG0_TX0 51
e_mdc NPHY_MDC 38 Configuration clock
e_mdio NPHY_MDIO 39 Configuration data

Before verification (the default PC NIC is a Gigabit NIC, otherwise it needed to be replaced). The host PC IP address needs to be confirmed first. In the DOS command window, type ipconfig -all command to check it. As an example, as shown in Figure 14.5.

Figure 14.5 PC end IP information

To facilitate subsequent experiments, provides PC a fixed IP address. Take this as an example, IP configuration is 192.169.0.100 (could be revised, but needs to be consistent to the IP address of target sending module, for Internet Protocol reason, IP address 169.XXX.X.X is not suggested ). Find Internet Protocol Version 4(TCP/IPv4) in Network and Sharing center. See Figure 14.6.

Figure 14.6 Configure PC end IP address

Since there is no ARP protocol content (binding IP address and MAC address of the development board) in this test, it needs to be bound manually through the DOS command window. In this test, the development board IP is set to 192.168.0.2 and the MAC address is set to 00-0A-35-01-FE-C0, (can be replaced by yourself) as shown in Fig 14. 7, the method is as follows: (Note: Run the DOS command window as an administrator)

Run the command: ARP -s 192.168.0.2 00-0A-35-01-FE-C0

View binding results: ARP -a

Figure 14.7 Address binding method 1

If a failure occurs while running the ARP command, it can be bound in another way, as shown in Figure 14.8:

  1. Enter the netsh i i show in command to view the number of the local connection, such as the “23” of the computer used this time.
  2. Enter netsh -c “i i” add neighbors 23 (number) “192.168.0.2” “00-0A-35-01-FE-C0”
  3. Enter arp -a to view the binding result (since it has been bound before, it will display as shown below in Figure 14.8)

Next, the DOS command window is used again for connectivity detection, as shown in Figure 14.9. Ping is an executable command that comes with the Windows family. Use it to check if the network can be connected. It can help analyze and determine network faults. Application format: Ping IP address (not host computer IP).

Figure 14.9 Send data

Start SignalTap II, after sending the command, as shown in Figure 14.10. The data is ordinary and the hardware fucntions well.

Figure 14.10 SignalTap II data capture

  1. Special IP core configuration (test2)

Because it is the RGMII interface, the data is bilateral along 4-bit data. Therefore, when data processing is performed inside the FPGA, it needs to be converted into 8-bit data. Go to Installed IP > Library > Basic Functions > I/O to find ALTDDIO_IN and ALTDDIO_OUT. IP core (ddio_in) is called to implement it, and after internal data processing, pass IP core (ddio_out) to convert 8-bit data into double-rolled edge 4-bit data transfer. It should be noted that, considering the enable signal and data signal synchronization, the enable signal is input into ddio for conversion. The specific settings are shown in Figure 14.11 and Figure 14.12.

Figure 14.11 ddio_in setting

Figure 14.12 ddio_out setting

Considering that the driving ability of the clock provided by the PHY chip is relatively poor, after the phase-locked loop processing, unlike the prior part, the input clock rxc selects the homologous input, as shown in Figure 14.13, and output C0 clock ddio_clk as the driving clock of two ddio IP cores, as shown in Figure 14.14, outputs the C1 clock txc as the data transmission clock (note that due to hardware circuit and timing reasons, txc needs to be 90° phase difference). See Figure 14.15.

Figure 14.13 PLL input clock setting

Figure 14.14 PLL output clock (c0) setting

Figure 14.15 PLL output clock (c1) setting

The three IP cores are instantiated into the previous loopback test, and the data transmission correctness test is performed. (It is necessary to notice the orderly timing. The ddio_out input data needs to be reversed. For details, refer to the project file (test2)). A network debugging assistant applet is used as an auxiliary testing tool. Program the board and verify it.

As shown in Figure 14.16, after setting the correct address and data type, the detection information (love you!) is sent through the host computer. The data packet is captured by Wireshark, as shown in Figure 14.17. The data is correctly transmitted back to the PC.

Figure 14.16 The host computer sends the test data

Figure 14.17 Correct reception of data on the PC side

  1. Complete Ethernet data transmission design

For complete Ethernet data transmission, it is necessary to have the receiving part of the data and the transmitting part of the data. For the convenience of experiment, the data sent by the PC is first sotred in the RAM. After reading via the transmitting end, it is sent to the PC. A series of data unpacking and packaging referring to the project file “ethernet”. A brief introduction to each module is as follows.

  1. Data receiving module (ip_receive)

The problem to be solved by this module is to detect and identify the data frame, unpack the valid data frame, and store the real data in the RAM.

always @ (posedge clk) begin

if (clr) begin

rx_state <= idle;

data_receive <= 1’b0;

end

else

case (rx_state)

 

idle :

begin

valid_ip_P <= 1’b0;

byte_counter <= 3’d0;

data_counter <= 10’d0;

mydata <= 32’d0;

state_counter <= 5’d0;

data_o_valid <= 1’b0;

ram_wr_addr <= 0;

if (e_rxdv == 1’b1) begin

if (datain[7:0] == 8’h55) begin //Receive the first 55//

rx_state <= six_55;

mydata <= {mydata[23:0], datain[7:0]};

end

else

rx_state <= idle;

end

end

 

six_55 :

begin //Receive 6 0x55//

if ((datain[7:0] == 8’h55) && (e_rxdv == 1’b1)) begin

if (state_counter == 5) begin

state_counter <= 0;

rx_state <= spd_d5;

end

else

state_counter <= state_counter + 1’b1;

end

else

rx_state <= idle;

end

 

spd_d5 :

begin //Receive 1 0xd5//

if ((datain[7:0] == 8’hd5) && (e_rxdv == 1’b1))

rx_state <= rx_mac;

else

rx_state <= idle;

end

 

rx_mac :

begin //Target mac address and source MAC address

if (e_rxdv == 1’b1) begin

if (state_counter < 5’d11) begin

mymac <= {mymac[87:0], datain};

state_counter <= state_counter + 1’b1;

end

else begin

board_mac <= mymac[87:40];

pc_mac <= {mymac[39:0], datain};

state_counter <= 5’d0;

if((mymac[87:72] == 16’h000a) && (mymac[71:56] == 16’h3501) && (mymac[55:40] == 16’hfec0)) //Judge the MAC Address is PRA006’s

rx_state <= rx_IP_Protocol;

else

rx_state <= idle;

end

end

else

rx_state <= idle;

end

 

rx_IP_Protocol :

begin //Receive 2 bytes IP TYPE

if (e_rxdv == 1’b1) begin

if (state_counter < 5’d1) begin

myIP_Prtcl <= {myIP_Prtcl[7:0], datain[7:0]};

state_counter <= state_counter+1’b1;

end

else begin

IP_Prtcl <= {myIP_Prtcl[7:0],datain[7:0]};

valid_ip_P <= 1’b1;

state_counter <= 5’d0;

rx_state <= rx_IP_layer;

end

end

else

rx_state <= idle;

end

 

rx_IP_layer :

begin //Receive 20 bytes udpvirtual header,ip address

valid_ip_P <= 1’b0;

if (e_rxdv == 1’b1) begin

if (state_counter < 5’d19) begin

myIP_layer <= {myIP_layer[151:0], datain[7:0]};

state_counter <= state_counter + 1’b1;

end

else begin

IP_layer <= {myIP_layer[151:0], datain[7:0]};

state_counter <= 5’d0;

rx_state <= rx_UDP_layer;

end

end

else

rx_state <= idle;

end

 

rx_UDP_layer :

begin //Receive 8 bytes UDP port number and total length of UDP packet

rx_total_length <= IP_layer[143:128];

pc_IP <= IP_layer[63:32];

board_IP <= IP_layer[31:0];

if (e_rxdv == 1’b1) begin

if (state_counter < 5’d7) begin

myUDP_layer <= {myUDP_layer[55:0], datain[7:0]};

state_counter <= state_counter + 1’b1;

end

else begin

UDP_layer <= {myUDP_layer[55:0], datain[7:0]};

rx_data_length <= myUDP_layer[23:8]; //Length of UDP packet

state_counter <= 5’d0;

rx_state <= rx_data;

end

end

else

rx_state <= idle;

end

 

rx_data :

begin // Receive UDP data

if (e_rxdv == 1’b1) begin

if (data_counter == rx_data_length-9) begin //Save the last ata

data_counter <= 0;

rx_state <= rx_finish;

ram_wr_addr <= ram_wr_addr + 1’b1;

data_o_valid <= 1’b1; //Write RAM

if (byte_counter == 3’d3) begin

data_o <= {mydata[23:0], datain[7:0]};

byte_counter <= 0;

end

else if (byte_counter==3’d2) begin

data_o <= {mydata[15:0], datain[7:0],8’h00}; //Less than 32-bit, add ’0’

byte_counter <= 0;

end

else if (byte_counter==3’d1) begin

data_o <= {mydata[7:0], datain[7:0], 16’h0000}; // Less than 32-bit, add ’0’

byte_counter <= 0;

end

else if (byte_counter==3’d0) begin

data_o <= {datain[7:0], 24’h000000}; // Less than 32-bit, add ’0’ byte_counter <= 0;

end

end

else begin

data_counter <= data_counter + 1’b1;

if (byte_counter < 3’d3) begin

mydata <= {mydata[23:0], datain[7:0]};

byte_counter <= byte_counter + 1’b1;

data_o_valid <= 1’b0;

end

else begin

data_o <= {mydata[23:0], datain[7:0]};

byte_counter <= 3’d0;

data_o_valid <= 1’b1// Accept 4bytes of data, write RAM request ram_wr_addr <= ram_wr_addr+1’b1;

end

end

end

else

rx_state <= idle;

end

 

rx_finish :

begin

data_o_valid <= 1’b0; //added for receive test//

data_receive <= 1’b1;

rx_state <= idle;

end

default : rx_state <= idle;

endcase

end

The receiving module is to perform step by step analysis on the received data.

Idle state: If 55 is received, it jumps to the six_55 state.

six_55 state: If it continues to receive six consecutive 55s, it will jump to the spd_d5 state, otherwise it will return the idle state.

spd_d5 state: If continues to receive d5, it proves that the complete packet preamble 55_55_55_55_55_55_55_d5 has been received, and jumps to rx_mac, otherwise it returns the idle transition.

rx_mac state: This part is the judgment of the target MAC address and the source MAC address. If it matches, it will jump to the rx_IP_Protocol state, otherwise it will return the idle state and resend.

rx_IP_Protocol state: Determine the type and length of the packet and jump to the rx_IP_layer state.

rx_IP_layer state: Receive 20 bytes of udp virtual header and IP address, jump to rx_UDP_layer state

rx_UDP_layer state: Receive 8-byte UDP port number and UDP packet length, jump to rx_data state

rx_data state: Receive UDP data, jump to rx_finish state

rx_finish state: A packet of data is received, and jumps to the idle state to wait for the arrival of the next packet of data.

  1. Data sending module (ip_send)

The main content of this module is to read out the data in the RAM, package and send the data with the correct packet protocol type (UDP). Before sending, the data is also checked by CRC.

initial begin

tx_state <= idle;

//Define IP header

preamble[0] <= 8’h55; //7 preambles 55, one frame start character d5

preamble[1] <= 8’h55;

preamble[2] <= 8’h55;

preamble[3] <= 8’h55;

preamble[4] <= 8’h55;

preamble[5] <= 8’h55;

preamble[6] <= 8’h55;

preamble[7] <= 8’hD5;

 

mac_addr[0] <= 8’h00; // Destination MAC address ff-ff-ff-ff-ff-ff, all ff is broadcast packet

mac_addr[1] <= 8’h0A; //Destination MAC address 00-0A-35-01-FE-C0, is the PC address used for this experiment. In the debugging phase changes content according to the value of actual PC

mac_addr[2] <= 8’h35;

mac_addr[3] <= 8’h01;

mac_addr[4] <= 8’hFE;

mac_addr[5] <= 8’hCO;

 

mac_addr[6] <= 8’h00; // Source MAC address 00-0A-35-01-FE-C0

mac_addr[7] <= 8’h0A; // Modify to the specified value according to actual needs

mac_addr[8] <= 8’h35;

mac_addr[9] <= 8’h01;

mac_addr[10]<= 8’hFE;

mac_addr[11]<= 8’hC0;

 

mac_addr[12]<= 8’h08; // 0800: IP packet type

mac_addr[13]<= 8’h00;

 

i<=0;

end

This part defines the preamble of the data packet, the MAC address of the PC, the MAC address of the development board, and the IP packet type. It should be noted that in the actual experiment, the MAC address of the PC needs to be modified, and the MAC address of the PC needs to be modified according to the address bound by itself, but the premise is that the consistency must be guaranteed. Otherwise the subsequent experiments will not receive data.

always @ (posedge clk) begin

case (tx_state)

idle :

begin

e_txen <= 1’b0;

crcen <= 1’b0;

crcre <= 1;

j <= 0;

dataout <= 0;

ram_rd_addr <= 1;

tx_data_counter <= 0;

if (time_counter == 32’h04000000) begin // Waiting for delay, sending a packet every once in a while

tx_state <= start;

time_counter <= 0;

end

else

time_counter <= time_counter + 1’b1;

end

 

start :

begin //IP header

ip_header[0] <= {16’h4500, tx_total_length}; // Version number: 4; length of the packet header: 20; total length of the IP packet

ip_header[1][31:16] <= ip_header[1][31:16]+1’b1; // Package serial number

ip_header[1][15:0] <= 16’h4000; //Fragment offset

ip_header[2] <= 32’h80110000; // Mema[2][15:0] Protocol: 17 (UDP)

ip_header[3] <= 32’hc0a80002; //192.168.0.2 source MAC

ip_header[4] <= 32’hc0a80010; //192.168.0.10 Destination address broadcast address

ip_header[5] <= 32’h1f901f90; //2-byte source port number and 2-byte destination port number

ip_header[6] <= {tx_data_length, 16’h0000}; //2 bytes of data length and 2 bytes of checksum (none)

tx_state <= make;

end

 

make :

begin // Generate a checksum of the header

if (i == 0) begin

check_buffer <= ip_header[0][15:0] + ip_header[0][31:16] +

ip_header[1][15:0] + ip_header[1][31:16] +

ip_header[2][15:0] + ip_header[2][31:16] +

ip_header[3][15:0] + ip_header[3][31:16] +

ip_header[4][15:0] + ip_header[4][31:16];

i <= i + 1’b1;

end

else if(i == 1) begin

check_buffer[15:0] <= check_buffer[31:16] + check_buffer[15:0];

i <= i+1’b1;

end

else begin

ip_header[2][15:0] <= ~check_buffer[15:0]; //header checksum

i <= 0;

tx_state <= send55;

end

end

 

send55 :

begin // Send 8 IP preambles: 7 55, 1 d5

e_txen <= 1’b1; // GMII data transmission is valid

crcre <= 1’b1; //Reset crc

if(i == 7) begin

dataout[7:0] <= preamble[i][7:0];

i <= 0;

tx_state <= sendmac;

end

else begin

dataout[7:0] <= preamble[i][7:0];

i <= i + 1’b1;

end

end

 

sendmac :

begin // Send destination MAC address, source MAC address and IP packet type

crcen <= 1’b1; // Crc check enable, crc32 data check starts from the target MAC

crcre <= 1’b0;

if (i == 13) begin

dataout[7:0] <= mac_addr[i][7:0];

i <= 0;

tx_state <= sendheader;

end

else begin

dataout[7:0] <= mac_addr[i][7:0];

i <= i + 1’b1;

end

end

 

sendheader :

begin // Send 7 32-bit IP headers

datain_reg <= datain; // Prepare the data needed to send

if(j == 6) begin

if(i == 0) begin

dataout[7:0] <= ip_header[j][31:24];

i <= i + 1’b1;

end

else if(i == 1) begin

dataout[7:0] <= ip_header[j][23:16];

i <= i + 1’b1;

end

else if(i == 2) begin

dataout[7:0] <= ip_header[j][15:8];

i <= i + 1’b1;

end

else if(i == 3) begin

dataout[7:0] <= ip_header[j][7:0];

i <= 0;

j <= 0;

tx_state <= senddata;

end

end

else begin

if(i == 0) begin

dataout[7:0] <= ip_header[j][31:24];

i <= i + 1’b1;

end

else if(i == 1) begin

dataout[7:0] <= ip_header[j][23:16];

i <= i + 1’b1;

end

else if(i == 2) begin

dataout[7:0] <= ip_header[j][15:8];

i <= i + 1’b1;

end

else if(i == 3) begin

dataout[7:0] <= ip_header[j][7:0];

i <= 0;

j <= j + 1’b1;

end

end

end

 

senddata :

begin //Send UDP packets

if(tx_data_counter == tx_data_length – 9) begin // Send the last data

tx_state <= sendcrc;

if (i == 0) begin

dataout[7:0] <= datain_reg[31:24];

i <= 0;

end

else if (i == 1) begin

dataout[7:0] <= datain_reg[23:16];

i <= 0;

end

else if (i == 2) begin

dataout[7:0] <= datain_reg[15:8];

i <= 0;

end

else if (i == 3) begin

dataout[7:0] <= datain_reg[7:0];

datain_reg <= datain; // Prepare data

i <= 0;

end

end

else begin // Send other packets

tx_data_counter <= tx_data_counter+1’b1;

if (i == 0) begin

dataout[7:0] <= datain_reg[31:24];

i <= i + 1’b1;

ram_rd_addr <= ram_rd_addr + 1’b1; // Add 1 to the RAM address, let the RAM output data in advance.

end

else if (i == 1) begin

dataout[7:0] <= datain_reg[23:16];

i <= i + 1’b1;

end

else if (i == 2) begin

dataout[7:0] <= datain_reg[15:8];

i <= i + 1’b1;

end

else if (i == 3) begin

dataout[7:0] <= datain_reg[7:0];

datain_reg <= datain; // Prepare data

i <= 0;

end

end

end

 

sendcrc :

begin // Send a 32-bit crc check

crcen <= 1’b0;

if (i == 0) begin

dataout[7:0] <= {~crc[24], ~crc[25], ~crc[26], ~crc[27], ~crc[28], ~crc[29], ~crc[30], ~crc[31]};

i <= i + 1’b1;

end

else begin

if (i == 1) begin

dataout[7:0] <= {~crc[16], ~crc[17], ~crc[18], ~crc[19], ~crc[20], ~crc[21], ~crc[22], ~crc[23]};

i <= i + 1’b1;

end

else if (i == 2) begin

dataout[7:0] <= {~crc[8], ~crc[9], ~crc[10], ~crc[11], ~crc[12], ~crc[13], ~crc[14], ~crc[15]};

i <= i + 1’b1;

end

else if (i == 3) begin

dataout[7:0] <= {~crc[0], ~crc[1], ~crc[2], ~crc[3], ~crc[4], ~crc[5], ~crc[6], ~crc[7]};

i <= 0;

tx_state <= idle;

end

end

end

 

default : tx_state <= idle;

endcase

end

Idle state: Waiting for delay, sending a packet at regular intervals and jumping to the start state.

start state: Send the packet header and jump to the make state.

make state: Generates the checksum of the header and jumps to the send55 state.

send55 status: Send 8 preambles and jump to the sendmac state.

sendmac state: Send the destination MAC address, source MAC address and IP packet class, and jump to the sendheader state.

sendheader state: Sends 7 32-bit IP headers and jumps to the senddata state.

senddata state: Send UDP packets and jump to the sendcrc state.

sendcrc state: Sends a 32-bit crc check and returns the idle state.

Thus, the entire packet of data is transmitted, and the idle state is returned to wait for the transmission of the next packet of data.

  1. CRC check module (crc)

The CRC32 check of an IP packet is calculated at the destination MAC Address and is calculated until the last data of a packet. The CRC32 verilog algorithm and polynomial of Ethernet can be generated directly at the following website: http://www.easics.com/webtools/crctool

  1. UDP data test module (UDP)

This module only needs to instantiate the first three sub-modules together, paying attention to the correctness of each connection.

  1. Top level module settings (ethernet)

The PLL, ddio_in, ddio_out, RAM, and UDP modules are instantiated to the top layer, and specific information is stored in advance in the RAM (Welcome To ZGZNXP World!). When there is no data input, the FPGA always sends this information. With data input, the received data is sent. Refer to the project files for more information.

14.4 Experiment Verification

The pin assignment of this test procedure is identical to that in Test 1.

Before programming the development board, it is necessary to note that the IP address of the PC and the MAC address of the development board must be determined and matched, otherwise the data will not be received.

As shown in Figure 14.18, the FPGA is keeping sending information to the PC. The entire transmitted packet can also be seen in Wireshark, as shown in Figure 14.19.

Figure 14.18 Send specific information

Figure 14.19 Specific information package

When the PC sends data to the FPGA, as shown in Figure 14.20, the entire packet arrives at the FPGA, and then the FPGA repackages the received data and sends it to the PC. See Figure 14.21, the network assistant also receives the transmitted data information accurately, as shown in Figure 14.22. Similarly, through SignalTap we can see the process of writing the received data, as shown in Figure 14.23.

Figure 14. 20 PC send data package

Figure 14.21 The FPGA repackages the received data and sends it to the PC

Figure 14.22 Information received by PC from FPGA

Figure 14.23 FPGA end data and stored in the RAM process

It should be noted that Ethernet II specifies the Ethernet frame data field is a minimum of 46 bytes, that is, the minimum Ethernet frame is 6+6+2+46+4=64. The 4-byte FCS is removed, so the packet capture is 60 bytes. When the length of the data field is less than 46 bytes, the MAC sublayer is padded after the data field to satisfy the data frame length of not less than 64 bytes. When communicating over a UDP LAN, “Hello World” often occurs for testing, but “Hello World” does not meet the minimum valid data (64-46) requirements. It is less than 18 bytes but the other party is still available for receiving, because data is complemented in the MAC sublayer of the link layer, less than 18 bytes are padded with ‘0’s. However, when the server is on the public network and the client is on the internal network, if less than 18 bytes of data is transmitted, the receiving end cannot receive the data. Therefore, if there is no data received, the information to be sent should be increased to more than 18 bytes.

Related posts